package org.dromara.device.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.vcp.VcpUtil;
import org.dromara.common.vcp.domain.SzSecret;
import org.dromara.common.web.core.BaseController;
import org.dromara.device.domain.bo.DeviceBo;
import org.dromara.device.domain.bo.DeviceConfigBo;
import org.dromara.device.domain.bo.DeviceInfoBo;
import org.dromara.device.domain.vo.DeviceConfigVo;
import org.dromara.device.domain.vo.DeviceInfoVo;
import org.dromara.device.domain.vo.DeviceVo;
import org.dromara.device.service.IDeviceConfigService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 设备管理-设备配置信息
 * 前端访问路由地址为:/device/config
 *
 * @author samuel
 * @date 2024-03-21
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/config")
public class DeviceConfigController extends BaseController {

    private final IDeviceConfigService deviceConfigService;

    /**
     * 根据门店分组 查询门店名称、设备数量、在线设备数量 离线设备数量
     */
//    @SaCheckPermission("device:config:group")
    @GetMapping("/group/store")
    public TableDataInfo<DeviceInfoVo> groupStore(DeviceInfoBo bo, Page<DeviceInfoVo> page) {
        List<DeviceInfoVo> list = deviceConfigService.groupStore(page, bo);
        return TableDataInfo.build(list);
    }

    /**
     * 查询设备管理-设备配置信息列表
     */
//    @SaCheckPermission("device:config:list")
    @GetMapping("/list")
    public TableDataInfo<DeviceVo> list(DeviceBo bo, PageQuery pageQuery) {
        return deviceConfigService.queryTableList(bo, pageQuery);
    }

    /**
     * 导出设备管理-设备配置信息列表
     */
    @SaCheckPermission("device:config:export")
    @Log(title = "设备管理-设备配置信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(DeviceConfigBo bo, HttpServletResponse response) {
        List<DeviceConfigVo> list = deviceConfigService.queryList(bo);
        ExcelUtil.exportExcel(list, "设备管理-设备配置信息", DeviceConfigVo.class, response);
    }

    /**
     * 获取设备管理-设备配置信息详细信息
     *
     * @param deviceId 主键
     */
//    @SaCheckPermission("device:config:query")
    @GetMapping("/{deviceId}")
    public R<DeviceVo> getInfo(@NotNull(message = "主键不能为空")
                               @PathVariable Long deviceId) {
        DeviceConfigVo deviceConfigVo = deviceConfigService.queryById(deviceId);
        if (ObjUtil.isNotNull(deviceConfigVo)) {
            DeviceVo deviceVo = BeanUtil.copyProperties(deviceConfigVo, DeviceVo.class);
            return R.ok(deviceVo);
        }
        return R.ok();
    }

    /**
     * 新增设备管理-设备配置信息
     */
    @SaCheckPermission("device:config:add")
    @Log(title = "设备管理-设备配置信息", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody DeviceBo bo) {
        return toAjax(deviceConfigService.bindDevice(bo));
    }

    /**
     * 修改设备管理-设备配置信息
     */
    @SaCheckPermission("device:config:edit")
    @Log(title = "设备管理-设备配置信息", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody DeviceBo bo) {
        return toAjax(deviceConfigService.updateBindBo(bo));
    }

    /**
     * 删除设备管理-设备配置信息
     *
     * @param deviceIds 主键串
     */
    @SaCheckPermission("device:config:remove")
    @Log(title = "设备管理-设备配置信息", businessType = BusinessType.DELETE)
    @DeleteMapping("/{deviceIds}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] deviceIds) {
        if (ObjUtil.isNotNull(deviceIds) && deviceIds.length > 5000) {
            return R.warn("请选择少于5000条数据");
        }
        return toAjax(deviceConfigService.remove(List.of(deviceIds)));
    }

    /**
     * 获取设备视频流
     *
     * @param deviceSns 设备编码集合
     */
//    @SaCheckPermission("device:config:live")
    @GetMapping("/liveUrl/{deviceSns}")
    public R<List<Map<String, String>>> getLiveUrl(@PathVariable String[] deviceSns) {

        List<DeviceConfigVo> vos = deviceConfigService.selectOnlineByDeviceSnList(deviceSns);
        if (CollUtil.isEmpty(vos)) {
            return R.ok();
        }
        List<SzSecret> szSecrets = BeanUtil.copyToList(vos, SzSecret.class);
        JSONObject params = new JSONObject();
        params.set("mediaType", "1");
        params.set("proto", "3");
        List<CompletableFuture<Map<String, String>>> futureList = szSecrets.stream().map(szSecret -> CompletableFuture.supplyAsync(() -> {
            String liveUrl = VcpUtil.getLiveUrl(szSecret, params.toString());
            Map<String, String> map = new HashMap<>();
            map.put("liveUrl", liveUrl);
            map.put("deviceSn", szSecret.getDeviceSn());
            return map;
        })).collect(Collectors.toList());

        // 等待所有异步操作完成并收集结果
        List<Map<String, String>> mapList = futureList.stream()
                .map(CompletableFuture::join) // 等待每个future完成，并获取其结果
                .collect(Collectors.toList());

        return R.ok(mapList);
    }
}
